<template>
  <div class="warehouse-visualization">
    <!-- 顶部标题 -->
    <div class="main-title">
      <div class="title-decoration left"></div>
      <h1>智慧库房一体化管理平台</h1>
      <div class="title-decoration right"></div>
    </div>

    <!-- 主要内容区域 -->
    <div class="main-content">
      <!-- 左侧控制面板 -->
      <div class="left-panel">
        <!-- 温湿度监控 -->
        <!-- 添加ref以便测量该模块的实际高度，用于同步第一行高度 -->
        <div class="monitor-section" ref="monitorSection">
          <div class="section-title">温湿度监控</div>
          <div class="gauge-container">
            <!-- 温度仪表盘 -->
            <div class="gauge-item">
              <div class="gauge-wrapper">
                <svg class="gauge-svg" viewBox="0 0 200 200">
                  <!-- 外圈 -->
                  <circle cx="100" cy="100" r="90" fill="none" stroke="#1a3a5c" stroke-width="2"/>
                  <!-- 内圈 -->
                  <circle cx="100" cy="100" r="75" fill="none" stroke="#2a4a6b" stroke-width="1"/>
                  <!-- 刻度线 -->
                  <g class="gauge-ticks">
                    <line v-for="i in 12" :key="i" 
                          :x1="100 + 70 * Math.cos((i - 3) * Math.PI / 6)" 
                          :y1="100 + 70 * Math.sin((i - 3) * Math.PI / 6)"
                          :x2="100 + 80 * Math.cos((i - 3) * Math.PI / 6)" 
                          :y2="100 + 80 * Math.sin((i - 3) * Math.PI / 6)"
                          stroke="#00d4ff" stroke-width="1"/>
                  </g>
                  <!-- 进度弧 -->
                  <path :d="getTemperatureArcPath()" fill="none" stroke="#00d4ff" stroke-width="3" stroke-linecap="round"/>
                  <!-- 中心点 -->
                  <circle cx="100" cy="100" r="3" fill="#00d4ff"/>
                </svg>
                <div class="gauge-content">
                  <div class="gauge-value">{{ Math.round(temperature) }}°C</div>
                  <div class="gauge-label">温度</div>
                </div>
              </div>
              <div class="gauge-status" :class="{ abnormal: temperature > 25 }">
                <span class="status-dot"></span>
                {{ temperature > 25 ? '异常' : '正常' }}
              </div>
            </div>

            <!-- 湿度仪表盘 -->
            <div class="gauge-item">
              <div class="gauge-wrapper">
                <svg class="gauge-svg" viewBox="0 0 200 200">
                  <!-- 外圈 -->
                  <circle cx="100" cy="100" r="90" fill="none" stroke="#1a3a5c" stroke-width="2"/>
                  <!-- 内圈 -->
                  <circle cx="100" cy="100" r="75" fill="none" stroke="#2a4a6b" stroke-width="1"/>
                  <!-- 刻度线 -->
                  <g class="gauge-ticks">
                    <line v-for="i in 12" :key="i" 
                          :x1="100 + 70 * Math.cos((i - 3) * Math.PI / 6)" 
                          :y1="100 + 70 * Math.sin((i - 3) * Math.PI / 6)"
                          :x2="100 + 80 * Math.cos((i - 3) * Math.PI / 6)" 
                          :y2="100 + 80 * Math.sin((i - 3) * Math.PI / 6)"
                          stroke="#00d4ff" stroke-width="1"/>
                  </g>
                  <!-- 进度弧 -->
                  <path :d="getHumidityArcPath()" fill="none" stroke="#00d4ff" stroke-width="3" stroke-linecap="round"/>
                  <!-- 中心点 -->
                  <circle cx="100" cy="100" r="3" fill="#00d4ff"/>
                </svg>
                <div class="gauge-content">
                  <div class="gauge-value">{{ Math.round(humidity) }}%RH</div>
                  <div class="gauge-label">湿度</div>
                </div>
              </div>
              <div class="gauge-status" :class="{ abnormal: humidity > 70 }">
                <span class="status-dot"></span>
                {{ humidity > 70 ? '异常' : '正常' }}
              </div>
            </div>
          </div>
        </div>

        <!-- 设备状态 -->
        <div class="device-section">
          <div class="section-title">设备状态</div>
          <div class="device-grid">
            <div class="device-item" v-for="device in devices" :key="device.name" @click="toggleDevice(device)">
              <div class="device-name">{{ device.name }}</div>
              <div class="device-status" :class="{ active: device.status }">
                {{ device.status ? '开启' : '关闭' }}
              </div>
            </div>
          </div>
        </div>

        <!-- 门禁管理模块已移除 -->
      </div>

      <!-- 中央监控区域 -->
      <div class="center-panel">
        <div class="monitor-container">
          <div class="monitor-header">
            <span>库房实时监控</span>
          </div>
          
          <!-- 馆藏量模块（替换原通道监控） -->
          <!-- 说明：展示四个核心指标，横向排列；每项采用「图标 + 数值 + 说明」的垂直布局。 -->
          <div class="collection-section">
            <div class="collection-header">
              <div class="collection-title-wrapper">
                <div class="collection-title-decoration left"></div>
                <!-- 标题增加科技感边框与霓虹质感 -->
                <div class="collection-title title-framed">馆藏量</div>
                <div class="collection-title-decoration right"></div>
              </div>
            </div>
            <div class="collection-grid">
              <!-- 卡片：图标容器内放置 3 个子元素，分别用于绘制不同图形组件（文件夹层、放大镜/堆叠、文件折角、六边形等） -->
              <div class="collection-item" v-for="item in holdingsItems" :key="item.key">
                <div class="stat-icon" :class="item.iconClass">
                  <span class="i i1"></span>
                  <span class="i i2"></span>
                  <span class="i i3"></span>
                </div>
                <div class="stat-content">
                  <div class="stat-value">{{ formatNumber(item.value) }}{{ item.suffix }}</div>
                  <div class="stat-label">{{ item.label }}</div>
                </div>
              </div>
            </div>
          </div>

          <!-- 图表区域 - 并排显示 -->
          <div class="charts-row">
            <!-- 温湿度曲线 -->
            <div class="chart-section">
              <div class="chart-header">
                <div class="chart-title-wrapper">
                  <div class="chart-title-decoration left"></div>
                  <div class="chart-title">温湿度曲线</div>
                  <div class="chart-title-decoration right"></div>
                </div>
                <div class="chart-legend">
                  <span class="legend-item temperature">● 温度</span>
                  <span class="legend-item humidity">● 湿度</span>
                </div>
              </div>
              <div class="chart-container">
                <div class="chart-border">
                  <!-- 移除固定宽高，改为由样式与脚本动态撑满容器 -->
                  <canvas ref="tempHumChart"></canvas>
                </div>
              </div>
            </div>

            <!-- 空气质量曲线 -->
            <div class="chart-section">
              <div class="chart-header">
                <div class="chart-title-wrapper">
                  <div class="chart-title-decoration left"></div>
                  <div class="chart-title">空气质量曲线</div>
                  <div class="chart-title-decoration right"></div>
                </div>
                <div class="chart-legend">
                  <span class="legend-item toc">● TOVC</span>
                  <span class="legend-item pm25">● PM2.5</span>
                </div>
              </div>
              <div class="chart-container">
                <div class="chart-border">
                  <!-- 移除固定宽高，改为由样式与脚本动态撑满容器 -->
                  <canvas ref="airQualityChart"></canvas>
                </div>
              </div>
            </div>
          </div>

          <!-- 上方已展示馆藏模块，此处不再重复显示 -->
        </div>
      </div>

      <!-- 右侧状态面板 -->
      <div class="right-panel">
        <!-- 报警状态 -->
        <div class="alarm-section">
          <div class="section-title">报警状态</div>
          
          <!-- 雷达动图 -->
          <div class="radar-container">
            <div class="radar-screen">
              <div class="radar-sweep" :style="{ transform: `rotate(${radarAngle}deg)` }"></div>
              <div class="radar-grid">
                <div class="radar-circle" v-for="i in 4" :key="i"></div>
                <div class="radar-line radar-line-h"></div>
                <div class="radar-line radar-line-v"></div>
              </div>
              <div class="radar-dots">
                <div 
                  v-for="(dot, index) in radarDots" 
                  :key="index"
                  class="radar-dot"
                  :style="{ 
                    left: dot.x + '%', 
                    top: dot.y + '%',
                    opacity: dot.opacity 
                  }"
                ></div>
              </div>
            </div>
          </div>

          <div class="alarm-list">
            <div class="alarm-item" v-for="alarm in alarms" :key="alarm.id" :class="alarm.level">
              <div class="alarm-icon"></div>
              <div class="alarm-text">{{ alarm.message }}</div>
            </div>
          </div>
        </div>

        <!-- 报警日志 -->
        <div class="log-section">
          <div class="section-title">报警日志</div>
          <div class="log-list">
            <div class="log-item" v-for="log in logs" :key="log.id">
              <div class="log-time">{{ log.time }}</div>
              <div class="log-message">{{ log.message }}</div>
            </div>
          </div>
        </div>

        <!-- UPS 状态模块已移除 -->
      </div>
    </div>


  </div>
</template>

<script>
export default {
  name: 'WarehouseVisualization',
  data() {
    return {
      temperature: 24.2,
      humidity: 68,
      scanLinePosition: 0,
      selectedChannel: '',
      animationFrameId: null,
      timeInterval: null,
      
      // 雷达动画相关
      radarAngle: 0,
      radarDots: [],
      
      // 设备列表
      devices: [
        { name: '除湿', status: false },
        { name: '加湿', status: true },
        { name: '制冷', status: false },
        { name: '制热', status: false },
        { name: '窗帘', status: true },
        { name: '新风', status: true },
        { name: '灯光', status: false },
        { name: '防鼠', status: true }
      ],
      
      // 通道列表
      channels: [
        { id: 1, name: '通道1 - 主入口监控' },
        { id: 2, name: '通道2 - 货架区域监控' },
        { id: 3, name: '通道3 - 温控区监控' },
        { id: 4, name: '通道4 - 安全出口监控' }
      ],
      
      // 报警信息
      alarms: [
        { id: 1, level: 'warning', message: '温度超出正常范围' },
        { id: 2, level: 'normal', message: '湿度监控正常' },
        { id: 3, level: 'error', message: '通道3信号异常' }
      ],
      
      // 报警日志
      logs: [
        { id: 1, time: '14:32', message: '温度报警解除' },
        { id: 2, time: '14:15', message: '湿度异常报警' },
        { id: 3, time: '13:58', message: '设备状态正常' },
        { id: 4, time: '13:45', message: '系统启动完成' }
      ],
      
      // 门禁管理数据
      doors: [
        { id: 1, name: '主入口', isOpen: false, isLocked: true },
        { id: 2, name: '安全出口', isOpen: false, isLocked: true },
        { id: 3, name: '货物通道', isOpen: true, isLocked: false },
        { id: 4, name: '员工通道', isOpen: false, isLocked: true }
      ],
      
      // UPS状态数据
      upsDevices: [
        { id: 1, label: 'UPS输入电压（RST）', value: '--V', status: 'normal', statusText: '正常' },
        { id: 2, label: 'UPS输入频率', value: '--Hz', status: 'normal', statusText: '正常' },
        { id: 3, label: '输出电压（RST）', value: '--A', status: 'normal', statusText: '正常' },
        { id: 4, label: '输出功率（RST）', value: '--W', status: 'normal', statusText: '正常' },
        { id: 5, label: 'UPS状态', value: '--', status: 'normal', statusText: '电源系统正常运行' }
      ],
      
      // 图表数据
      tempData: [],
      humData: [],
      airQualityData: []
      ,
      // 馆（室）藏数量数据（示例数据，可与后端接口对接）
      // 包含：总库存量、使用量、空余量、项目数量、总卷数量、卷内数量、档案页数、数字化率、档案利用数
      // 馆藏量统计（示例数据，可替换为接口返回）
      collectionStats: {
        totalInventory: 125432,
        used: 45210,
        available: 80222,
        projectCount: 218,
        totalVolumes: 5389,
        inVolumeCount: 17432,
        pageCount: 862153,
        itemCount: 29384, // 新增：件数（示例）
        digitizationRate: 67.5,
        utilizationCount: 1298
      }
    }
  },
  computed: {
    // 馆藏量四项指标：案卷数、卷内件数、件数、数字化率
    holdingsItems() {
      const s = this.collectionStats
      return [
        { key: 'volumes', label: '案卷数', value: s.totalVolumes, iconClass: 'icon-folder-multi', suffix: '' },
        { key: 'inVolumeItems', label: '卷内件数', value: s.inVolumeCount, iconClass: 'icon-stack-search', suffix: '' },
        { key: 'items', label: '件数', value: s.itemCount, iconClass: 'icon-doc-blue', suffix: '' },
        { key: 'digitalRate', label: '数字化率', value: s.digitizationRate, iconClass: 'icon-hex3-orange', suffix: '%' }
      ]
    }
  },
  mounted() {
    this.initChartData()
    this.startAnimations()
    this.initCharts()
    
    // 绑定窗口尺寸变化事件，保持图表自适应填满容器
    // 注意：Vue2 使用 beforeDestroy 移除事件
    window.addEventListener('resize', this.resizeCharts)
    // 同步第一行高度（以左侧“温湿度监控”的实际高度为准），保证第二行顶部齐平
    window.addEventListener('resize', this.syncRowHeights)
    // 初次渲染后进行一次同步，避免初始误差
    this.$nextTick(() => {
      this.syncRowHeights()
    })
    
    // 定时更新数据
    setInterval(() => {
      this.updateSensorData()
      this.updateChartData()
    }, 3000)
  },
  beforeDestroy() {
    if (this.animationFrameId) {
      cancelAnimationFrame(this.animationFrameId)
    }
    if (this.timeInterval) {
      clearInterval(this.timeInterval)
    }
    // 解绑窗口尺寸变化事件，避免内存泄漏
    window.removeEventListener('resize', this.resizeCharts)
    window.removeEventListener('resize', this.syncRowHeights)
  },
  methods: {
    // 切换设备状态
    toggleDevice(device) {
      device.status = !device.status
    },
    
    // 数值格式化：带千分位分隔，确保与中文环境一致
    formatNumber(value) {
      if (value === null || value === undefined) return '--'
      const num = Number(value)
      if (Number.isNaN(num)) return value
      return num.toLocaleString('zh-CN')
    },
    

    
    // 获取通道名称
    getChannelName(channelId) {
      const channel = this.channels.find(c => c.id == channelId)
      return channel ? channel.name : ''
    },

    // 计算温度仪表盘弧形路径
    getTemperatureArcPath() {
      const centerX = 100
      const centerY = 100
      const radius = 85
      const minTemp = 0
      const maxTemp = 50
      const currentTemp = parseFloat(this.temperature)
      
      // 计算角度 (从-135度到135度，总共270度)
      const startAngle = -135 * Math.PI / 180
      const endAngle = 135 * Math.PI / 180
      const currentAngle = startAngle + (currentTemp - minTemp) / (maxTemp - minTemp) * (endAngle - startAngle)
      
      // 计算起点和终点坐标
      const startX = centerX + radius * Math.cos(startAngle)
      const startY = centerY + radius * Math.sin(startAngle)
      const endX = centerX + radius * Math.cos(currentAngle)
      const endY = centerY + radius * Math.sin(currentAngle)
      
      // 判断是否为大弧
      const largeArcFlag = Math.abs(currentAngle - startAngle) > Math.PI ? 1 : 0
      
      return `M ${startX} ${startY} A ${radius} ${radius} 0 ${largeArcFlag} 1 ${endX} ${endY}`
    },

    // 计算湿度仪表盘弧形路径
    getHumidityArcPath() {
      const centerX = 100
      const centerY = 100
      const radius = 85
      const minHum = 0
      const maxHum = 100
      const currentHum = parseFloat(this.humidity)
      
      // 计算角度 (从-135度到135度，总共270度)
      const startAngle = -135 * Math.PI / 180
      const endAngle = 135 * Math.PI / 180
      const currentAngle = startAngle + (currentHum - minHum) / (maxHum - minHum) * (endAngle - startAngle)
      
      // 计算起点和终点坐标
      const startX = centerX + radius * Math.cos(startAngle)
      const startY = centerY + radius * Math.sin(startAngle)
      const endX = centerX + radius * Math.cos(currentAngle)
      const endY = centerY + radius * Math.sin(currentAngle)
      
      // 判断是否为大弧
      const largeArcFlag = Math.abs(currentAngle - startAngle) > Math.PI ? 1 : 0
      
      return `M ${startX} ${startY} A ${radius} ${radius} 0 ${largeArcFlag} 1 ${endX} ${endY}`
    },
    
    // 更新传感器数据
    updateSensorData() {
      this.temperature = (Math.random() * 8 + 20).toFixed(1)
      this.humidity = Math.floor(Math.random() * 30 + 50)
    },
    
    startAnimations() {
      const animate = () => {
        // 扫描线动画
        this.scanLinePosition = (this.scanLinePosition + 2) % 300
        
        // 雷达扫描动画
        this.radarAngle = (this.radarAngle + 2) % 360
        
        // 更新雷达点
        this.updateRadarDots()
        
        // 模拟温湿度变化
        if (Math.random() < 0.01) {
          this.temperature = (23 + Math.random() * 4).toFixed(1)
          this.humidity = (60 + Math.random() * 10).toFixed(1)
        }
        
        this.animationFrameId = requestAnimationFrame(animate)
      }
      animate()
    },
    
    // 更新雷达点
    updateRadarDots() {
      // 随机生成雷达点
      if (Math.random() < 0.1) {
        const newDot = {
          x: Math.random() * 80 + 10,
          y: Math.random() * 80 + 10,
          opacity: 1,
          id: Date.now()
        }
        this.radarDots.push(newDot)
      }
      
      // 更新现有点的透明度
      this.radarDots = this.radarDots.map(dot => ({
        ...dot,
        opacity: dot.opacity - 0.02
      })).filter(dot => dot.opacity > 0)
    },
    
    // 初始化图表数据
    initChartData() {
      this.tempData = Array.from({ length: 24 }, (_, i) => ({
        time: i,
        value: Math.random() * 10 + 20
      }))
      this.humData = Array.from({ length: 24 }, (_, i) => ({
        time: i,
        value: Math.random() * 20 + 50
      }))
      this.airQualityData = Array.from({ length: 24 }, (_, i) => ({
        time: i,
        value: Math.random() * 50 + 50
      }))
    },
    
    // 更新图表数据
    updateChartData() {
      // 移除第一个数据点，添加新的数据点
      this.tempData.shift()
      this.tempData.push({
        time: this.tempData.length,
        value: parseFloat(this.temperature)
      })
      
      this.humData.shift()
      this.humData.push({
        time: this.humData.length,
        value: this.humidity
      })
      
      this.airQualityData.shift()
      this.airQualityData.push({
        time: this.airQualityData.length,
        value: Math.random() * 50 + 50
      })
      
      // 重绘图表
      this.drawCharts()
    },
    
    // 初始化图表：在 DOM 就绪后同步 canvas 尺寸并绘制
    initCharts() {
      this.$nextTick(() => {
        this.resizeCharts()
      })
    },
    
    // 同步 canvas 像素尺寸与父容器尺寸，并重绘图表
    // 目的：让曲线图表充分占满模块空间，减少黑色空白区域
    resizeCharts() {
      const setup = (canvas) => {
        if (!canvas) return
        // 先用样式让 canvas 填满父容器
        canvas.style.width = '100%'
        canvas.style.height = '100%'
        // 再同步像素尺寸为实际内容盒尺寸，避免缩放造成模糊
        const w = canvas.clientWidth
        const h = canvas.clientHeight
        if (w > 0 && h > 0) {
          canvas.width = w
          canvas.height = h
        }
      }
      setup(this.$refs.tempHumChart)
      setup(this.$refs.airQualityChart)
      // 尺寸更新后重绘
      this.drawCharts()
    },
    
    // 绘制图表
    drawCharts() {
      this.drawTempHumChart()
      this.drawAirQualityChart()
    },
    
    // 绘制温湿度图表（自适应填充容器，减少留白）
    drawTempHumChart() {
      const canvas = this.$refs.tempHumChart
      if (!canvas) return
      
      const ctx = canvas.getContext('2d')
      const width = canvas.width
      const height = canvas.height
      const padding = 10 // 内边距，避免线条紧贴边框被剪裁
      const contentW = Math.max(0, width - padding * 2)
      const contentH = Math.max(0, height - padding * 2)
      
      // 清空画布
      ctx.clearRect(0, 0, width, height)
      
      // 绘制背景网格（在内容区域内）
      ctx.strokeStyle = '#1a3a5c'
      ctx.lineWidth = 0.5
      const gridLines = 5
      for (let i = 0; i <= gridLines; i++) {
        const y = padding + (contentH / gridLines) * i
        ctx.beginPath()
        ctx.moveTo(padding, y)
        ctx.lineTo(width - padding, y)
        ctx.stroke()
      }
      
      // 计算温度与湿度的动态上下界，确保曲线更饱满
      const tempVals = this.tempData.map(p => p.value)
      const humVals = this.humData.map(p => p.value)
      const tMin = Math.min(...tempVals)
      const tMax = Math.max(...tempVals)
      const hMin = Math.min(...humVals)
      const hMax = Math.max(...humVals)
      const tPad = Math.max(1, (tMax - tMin) * 0.1)
      const hPad = Math.max(2, (hMax - hMin) * 0.1)
      const tRangeMin = tMin - tPad
      const tRangeMax = tMax + tPad
      const hRangeMin = hMin - hPad
      const hRangeMax = hMax + hPad
      
      const xStep = this.tempData.length > 1 ? contentW / (this.tempData.length - 1) : 0
      const xAt = (i) => padding + xStep * i
      const yMap = (val, min, max) => {
        if (max === min) return padding + contentH / 2
        return padding + (contentH - ((val - min) / (max - min)) * contentH)
      }
      
      // 绘制温度曲线
      ctx.strokeStyle = '#ff6b6b'
      ctx.lineWidth = 2
      ctx.beginPath()
      this.tempData.forEach((point, index) => {
        const x = xAt(index)
        const y = yMap(point.value, tRangeMin, tRangeMax)
        if (index === 0) ctx.moveTo(x, y)
        else ctx.lineTo(x, y)
      })
      ctx.stroke()
      
      // 绘制湿度曲线
      ctx.strokeStyle = '#4ecdc4'
      ctx.lineWidth = 2
      ctx.beginPath()
      this.humData.forEach((point, index) => {
        const x = xAt(index)
        const y = yMap(point.value, hRangeMin, hRangeMax)
        if (index === 0) ctx.moveTo(x, y)
        else ctx.lineTo(x, y)
      })
      ctx.stroke()
    },
    
    // 绘制空气质量图表（自适应填充容器，减少留白）
    drawAirQualityChart() {
      const canvas = this.$refs.airQualityChart
      if (!canvas) return
      
      const ctx = canvas.getContext('2d')
      const width = canvas.width
      const height = canvas.height
      const padding = 10
      const contentW = Math.max(0, width - padding * 2)
      const contentH = Math.max(0, height - padding * 2)
      
      // 清空画布
      ctx.clearRect(0, 0, width, height)
      
      // 绘制背景网格（在内容区域内）
      ctx.strokeStyle = '#1a3a5c'
      ctx.lineWidth = 0.5
      const gridLines = 5
      for (let i = 0; i <= gridLines; i++) {
        const y = padding + (contentH / gridLines) * i
        ctx.beginPath()
        ctx.moveTo(padding, y)
        ctx.lineTo(width - padding, y)
        ctx.stroke()
      }
      
      // 计算空气质量的动态上下界
      const values = this.airQualityData.map(p => p.value)
      const vMin = Math.min(...values)
      const vMax = Math.max(...values)
      const vPad = Math.max(2, (vMax - vMin) * 0.1)
      const rangeMin = vMin - vPad
      const rangeMax = vMax + vPad
      const xStep = this.airQualityData.length > 1 ? contentW / (this.airQualityData.length - 1) : 0
      const xAt = (i) => padding + xStep * i
      const yMap = (val) => {
        if (rangeMax === rangeMin) return padding + contentH / 2
        return padding + (contentH - ((val - rangeMin) / (rangeMax - rangeMin)) * contentH)
      }
      
      // 绘制空气质量曲线
      ctx.strokeStyle = '#45b7d1'
      ctx.lineWidth = 2
      ctx.beginPath()
      this.airQualityData.forEach((point, index) => {
        const x = xAt(index)
        const y = yMap(point.value)
        if (index === 0) ctx.moveTo(x, y)
        else ctx.lineTo(x, y)
      })
      ctx.stroke()
    },

    // 动态同步第一行高度到 CSS 变量 --row1-height
    // 说明：测量左侧“温湿度监控”模块的实际高度，并设置到主内容容器上，
    //       使中列“馆藏量”和右列“报警状态”第一行高度保持一致，
    //       从而让第二行（设备状态、温湿度曲线、空气质量曲线、报警日志）顶部齐平。
    syncRowHeights() {
      try {
        const mainContent = this.$el && this.$el.querySelector && this.$el.querySelector('.main-content')
        const leftFirstRow = this.$refs && this.$refs.monitorSection
        const monitorContainer = this.$el && this.$el.querySelector && this.$el.querySelector('.center-panel .monitor-container')
        const monitorHeader = this.$el && this.$el.querySelector && this.$el.querySelector('.center-panel .monitor-header')
        const collectionSection = this.$el && this.$el.querySelector && this.$el.querySelector('.center-panel .collection-section')
        const alarmSection = this.$el && this.$el.querySelector && this.$el.querySelector('.right-panel .alarm-section')
        if (!mainContent || !leftFirstRow) return

        // 左侧第一行（温湿度监控）实际高度
        const leftH = leftFirstRow.offsetHeight

        if (leftH && leftH > 0) {
          // 同步变量（右侧报警保持与左侧一致）
          mainContent.style.setProperty('--row1-height', `${leftH}px`)

          // 计算中列第一行（馆藏量）的目标高度：左侧高度扣除中央头部和列间gap
          const headerH = monitorHeader ? monitorHeader.offsetHeight : 0
          let rowGap = 15
          if (monitorContainer) {
            const styles = window.getComputedStyle(monitorContainer)
            // rowGap 在部分浏览器下为 "row-gap"，在部分环境中为 "gap"
            const gapStr = styles.getPropertyValue('row-gap') || styles.getPropertyValue('gap')
            const parsed = parseFloat(gapStr)
            if (!Number.isNaN(parsed)) rowGap = parsed
          }
          const centerBasis = Math.max(0, leftH - headerH - rowGap)

          // 将计算后的高度应用到馆藏量模块，确保第二行顶部齐平
          if (collectionSection) {
            collectionSection.style.flex = `0 0 ${centerBasis}px`
          }

          // 右侧报警模块若存在，确保其第一行高度严格等于左侧高度（防止样式变量未生效时的偏差）
          if (alarmSection) {
            alarmSection.style.flex = `0 0 ${leftH}px`
          }
        }
      } catch (e) {
        // 忽略测量异常，避免影响页面正常渲染
      }
    }
  }
}
</script>

<style scoped>
.warehouse-visualization {
  width: 100%;
  height: 100vh;
  background: linear-gradient(135deg, #0a1428 0%, #1a2332 50%, #0f1b2e 100%);
  color: #ffffff;
  font-family: 'Microsoft YaHei', sans-serif;
  overflow: hidden;
  position: relative;
}

/* 顶部标题 */
.main-title {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 15px 0;
  background: linear-gradient(90deg, transparent 0%, rgba(0, 212, 255, 0.1) 50%, transparent 100%);
  border-bottom: 1px solid rgba(0, 212, 255, 0.3);
  position: relative;
}

.main-title h1 {
  font-size: 24px;
  font-weight: bold;
  color: #00d4ff;
  text-shadow: 0 0 10px rgba(0, 212, 255, 0.5);
  margin: 0;
  letter-spacing: 2px;
}

.title-decoration {
  width: 100px;
  height: 2px;
  background: linear-gradient(90deg, transparent, #00d4ff, transparent);
  margin: 0 20px;
}

/* 主要内容区域 */
.main-content {
  /* 定义第一行统一高度与列间距变量，供子模块复用 */
  --row1-height: 270px; /* 第一行统一高度，保证第二行顶部齐平 */
  --row-gap: 15px;      /* 各列上下模块间统一间距 */
  display: grid;
  grid-template-columns: 250px 1fr 320px;
  gap: 15px;
  padding: 15px;
  height: calc(100vh - 80px);
}

/* 左侧面板样式 */
.left-panel {
  background: linear-gradient(145deg, rgba(26, 58, 92, 0.4), rgba(15, 27, 46, 0.6));
  border: 1px solid rgba(0, 212, 255, 0.3);
  border-radius: 8px;
  padding: 15px;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
  display: flex;
  flex-direction: column;
  gap: var(--row-gap); /* 统一与中、右列的行间距 */
}

.monitor-section, .device-section {
  background: rgba(0, 212, 255, 0.05);
  border: 1px solid rgba(0, 212, 255, 0.2);
  border-radius: 6px;
  padding: 15px;
}

/* 第一行：温湿度监控固定统一高度，确保与其他列第一行底部齐平 */
.monitor-section {
  flex: 0 0 var(--row1-height);
}

/* 第二行：设备状态占据剩余空间，顶部与同列统一 gap 距离 */
.device-section {
  flex: 1;
}

.section-title {
  color: #00d4ff;
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 15px;
  text-align: center;
  border-bottom: 1px solid rgba(0, 212, 255, 0.3);
  padding-bottom: 8px;
}

.gauge-container {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.gauge-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.gauge-wrapper {
  position: relative;
  width: 120px;
  height: 120px;
}

.gauge-svg {
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}

.gauge-content {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
  z-index: 10;
}

.gauge-value {
  font-size: 16px;
  font-weight: bold;
  color: #00d4ff;
  text-shadow: 0 0 8px rgba(0, 212, 255, 0.6);
  margin-bottom: 2px;
}

.gauge-label {
  font-size: 12px;
  color: #8cc8ff;
}

.gauge-status {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  color: #00ff88;
  padding: 4px 8px;
  background: rgba(0, 255, 136, 0.1);
  border: 1px solid rgba(0, 255, 136, 0.3);
  border-radius: 12px;
}

.gauge-status.abnormal {
  color: #ff6b6b;
  background: rgba(255, 107, 107, 0.1);
  border-color: rgba(255, 107, 107, 0.3);
}

.status-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #00ff88;
  animation: pulse 2s infinite;
}

.gauge-status.abnormal .status-dot {
  background: #ff6b6b;
}

@keyframes pulse {
  0%, 100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.7;
    transform: scale(1.2);
  }
}

.device-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.device-item {
  background: rgba(0, 212, 255, 0.1);
  border: 1px solid rgba(0, 212, 255, 0.3);
  border-radius: 4px;
  padding: 8px;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
}

.device-item:hover {
  background: rgba(0, 212, 255, 0.2);
  box-shadow: 0 0 8px rgba(0, 212, 255, 0.4);
}

.device-name {
  font-size: 12px;
  color: #8cc8ff;
  margin-bottom: 4px;
}

.device-status {
  font-size: 10px;
  color: #666;
}

.device-status.active {
  color: #00ff88;
}

/* 中央面板样式 */
.center-panel {
  background: linear-gradient(145deg, rgba(26, 58, 92, 0.4), rgba(15, 27, 46, 0.6));
  border: 1px solid rgba(0, 212, 255, 0.3);
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
  height: 100%;
  display: flex;
  flex-direction: column;
}

.monitor-container {
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--row-gap); /* 统一与左右列的行间距 */
}

.monitor-header {
  background: linear-gradient(90deg, rgba(0, 212, 255, 0.2), transparent);
  border-bottom: 1px solid rgba(0, 212, 255, 0.3);
  padding: 10px 15px;
  margin: -15px -15px 15px -15px;
  border-radius: 8px 8px 0 0;
}

.monitor-header span {
  color: #00d4ff;
  font-weight: bold;
  font-size: 14px;
}

.channel-section {
  margin-bottom: 15px;
}

.channel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px;
  background: rgba(0, 212, 255, 0.1);
  border: 1px solid rgba(0, 212, 255, 0.3);
  border-radius: 6px;
}

.channel-header span {
  color: #00d4ff;
  font-size: 12px;
  font-weight: bold;
}

.channel-select {
  background: rgba(0, 20, 40, 0.8);
  border: 1px solid rgba(0, 212, 255, 0.3);
  border-radius: 4px;
  color: #8cc8ff;
  padding: 4px 8px;
  font-size: 12px;
}

.channel-select option {
  background: #0a1428;
  color: #8cc8ff;
}

.video-monitor {
  background: #0f1419;
  border: 1px solid #2a4a6b;
  border-radius: 6px;
  position: relative;
  overflow: hidden;
  height: 300px;
}

.video-screen {
  width: 100%;
  height: 100%;
  background: linear-gradient(145deg, rgba(0, 20, 40, 0.8), rgba(0, 30, 60, 0.6));
  border: 2px solid rgba(0, 212, 255, 0.4);
  border-radius: 6px;
  position: relative;
  overflow: hidden;
}

.video-content {
  width: 100%;
  height: 100%;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
}

.grid-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-image: 
    linear-gradient(rgba(0, 212, 255, 0.1) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 212, 255, 0.1) 1px, transparent 1px);
  background-size: 20px 20px;
  pointer-events: none;
}

.scan-line {
  position: absolute;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, #00d4ff, transparent);
  box-shadow: 0 0 10px #00d4ff;
}

/* 中央面板图表样式 */
.charts-row {
  display: flex;
  gap: 20px;
  width: 100%;
  flex: 1;
  margin-top: 0; /* 由父容器 monitor-container 的 gap 控制上下间距，避免与左右列不一致 */
  align-items: stretch;
}

.center-panel .chart-section {
  background: linear-gradient(135deg, #0a0e14 0%, #1a1f2e 100%);
  border: 1px solid #00d4ff;
  border-radius: 8px;
  padding: 15px;
  flex: 1;
  position: relative;
  box-shadow: 0 0 20px rgba(0, 212, 255, 0.3);
  display: flex;
  flex-direction: column;
  height: 100%;
}

.center-panel .chart-section::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border-radius: 8px;
  padding: 1px;
  background: linear-gradient(45deg, #00d4ff, #0066cc, #00d4ff);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: exclude;
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask-composite: exclude;
  pointer-events: none;
}

.center-panel .chart-header {
  margin-bottom: 15px;
}

.center-panel .chart-title-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 8px;
}

.center-panel .chart-title-decoration {
  height: 1px;
  background: linear-gradient(90deg, transparent, #00d4ff, transparent);
  flex: 1;
}

.center-panel .chart-title-decoration.left {
  margin-right: 15px;
}

.center-panel .chart-title-decoration.right {
  margin-left: 15px;
}

.center-panel .chart-title {
  color: #00d4ff;
  font-size: 16px;
  font-weight: bold;
  text-shadow: 0 0 10px #00d4ff;
  white-space: nowrap;
  text-transform: uppercase;
  letter-spacing: 1px;
}

.center-panel .chart-legend {
  display: flex;
  justify-content: center;
  gap: 20px;
}

.center-panel .legend-item {
  font-size: 12px;
  color: #8cc8ff;
}

.center-panel .legend-item.temperature {
  color: #ff6b6b;
}

.center-panel .legend-item.humidity {
  color: #4ecdc4;
}

.center-panel .legend-item.toc {
  color: #ffd93d;
}

.center-panel .legend-item.pm25 {
  color: #6bcf7f;
}

.center-panel .chart-container {
  /* 取消居中，改为拉伸填充容器，减少留白 */
  display: flex;
  flex: 1;
  height: 100%;
  min-height: 280px;
}

.center-panel .chart-border {
  position: relative;
  background: #0a0e14;
  border: 1px solid #2a4a6b;
  border-radius: 6px;
  padding: 10px; /* 适当收紧内边距，提升可用绘制面积 */
  width: 100%;
  height: 100%;
  display: block; /* 让内部 canvas 直接按 100% 尺寸伸展 */
}

.center-panel .chart-border::before {
  content: '';
  position: absolute;
  top: -1px;
  left: -1px;
  right: -1px;
  bottom: -1px;
  background: linear-gradient(45deg, #00d4ff, transparent, #00d4ff);
  border-radius: 6px;
  z-index: -1;
  opacity: 0.5;
}

.center-panel .chart-container canvas {
  /* 保证样式尺寸始终随父容器变化 */
  width: 100%;
  height: 100%;
  border-radius: 4px;
}

.no-signal {
  color: #666;
  font-size: 16px;
  z-index: 10;
}

.video-info {
  z-index: 10;
  text-align: center;
}

.channel-name {
  color: #00d4ff;
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 5px;
}

.video-status {
  color: #00ff88;
  font-size: 12px;
}

/* 右侧面板样式 */
.right-panel {
  background: linear-gradient(145deg, rgba(26, 58, 92, 0.4), rgba(15, 27, 46, 0.6));
  border: 1px solid rgba(0, 212, 255, 0.3);
  border-radius: 8px;
  padding: 15px;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
  display: flex;
  flex-direction: column;
  gap: var(--row-gap); /* 与左、中列保持一致的模块间距 */
  height: 100%;
}

.chart-section {
  background: rgba(0, 212, 255, 0.05);
  border: 1px solid rgba(0, 212, 255, 0.2);
  border-radius: 6px;
  padding: 10px;
}

.chart-title {
  color: #00d4ff;
  font-size: 12px;
  font-weight: bold;
  margin-bottom: 10px;
  text-align: center;
  border-bottom: 1px solid rgba(0, 212, 255, 0.3);
  padding-bottom: 5px;
}

.chart-container {
  display: flex;
  justify-content: center;
  align-items: center;
}

.chart-container canvas {
  background: rgba(0, 20, 40, 0.5);
  border-radius: 4px;
}

.alarm-section {
  background: #0f1419;
  border: 1px solid #2a4a6b;
  border-radius: 6px;
  padding: 15px;
  flex: 0 0 var(--row1-height); /* 第一行统一高度，保证第二行顶部齐平 */
  display: flex;
  flex-direction: column;
}

/* 雷达动图样式 */
.radar-container {
  margin: 15px 0;
  display: flex;
  justify-content: center;
}

.radar-screen {
  width: 120px;
  height: 120px;
  background: radial-gradient(circle, #0a1428 0%, #1a2332 100%);
  border: 2px solid #00d4ff;
  border-radius: 50%;
  position: relative;
  overflow: hidden;
}

.radar-grid {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.radar-circle {
  position: absolute;
  border: 1px solid rgba(0, 212, 255, 0.3);
  border-radius: 50%;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.radar-circle:nth-child(1) { width: 30px; height: 30px; }
.radar-circle:nth-child(2) { width: 60px; height: 60px; }
.radar-circle:nth-child(3) { width: 90px; height: 90px; }
.radar-circle:nth-child(4) { width: 116px; height: 116px; }

.radar-line {
  position: absolute;
  background: rgba(0, 212, 255, 0.3);
}

.radar-line-h {
  top: 50%;
  left: 0;
  right: 0;
  height: 1px;
  transform: translateY(-50%);
}

.radar-line-v {
  left: 50%;
  top: 0;
  bottom: 0;
  width: 1px;
  transform: translateX(-50%);
}

.radar-sweep {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 58px;
  height: 1px;
  background: linear-gradient(90deg, #00d4ff, transparent);
  transform-origin: 0 50%;
  animation: none;
}

.radar-dots {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.radar-dot {
  position: absolute;
  width: 3px;
  height: 3px;
  background: #ff6b35;
  border-radius: 50%;
  box-shadow: 0 0 6px #ff6b35;
  transform: translate(-50%, -50%);
}

.log-section {
  background: #0f1419;
  border: 1px solid #2a4a6b;
  border-radius: 6px;
  padding: 15px;
  flex: 1.5;
  display: flex;
  flex-direction: column;
}

.alarm-list {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.log-list {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.alarm-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px;
  margin-bottom: 5px;
  border-radius: 4px;
  font-size: 11px;
}

.alarm-item.warning {
  background: rgba(255, 170, 0, 0.1);
  border-left: 3px solid #ffaa00;
}

.alarm-item.error {
  background: rgba(255, 107, 107, 0.1);
  border-left: 3px solid #ff6b6b;
}

.alarm-item.normal {
  background: rgba(0, 255, 136, 0.1);
  border-left: 3px solid #00ff88;
}

.alarm-icon {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

.alarm-text {
  color: #8cc8ff;
}

.log-item {
  display: flex;
  gap: 8px;
  padding: 4px;
  margin-bottom: 4px;
  font-size: 10px;
  border-bottom: 1px solid rgba(0, 212, 255, 0.1);
}

.log-time {
  color: #666;
  min-width: 35px;
}

.log-message {
  color: #8cc8ff;
}



/* 馆（室）藏数量模块样式 */
.center-panel .collection-section {
  background: linear-gradient(135deg, #0a0e14 0%, #1a1f2e 100%);
  border: 1px solid #00d4ff;
  border-radius: 8px;
  padding: 15px;
  margin-top: 0; /* 由父容器 monitor-container 的 gap 控制与上方标题的间距 */
  flex: 0 0 var(--row1-height); /* 统一第一行高度，与左侧温湿度监控下边齐 */
  position: relative;
  box-shadow: 0 0 20px rgba(0, 212, 255, 0.25);
  /* 让内部网格可以按容器剩余空间自适应填充 */
  display: flex;
  flex-direction: column;
  --collection-gap: 14px; /* 默认卡片间距，可根据需要调整或改为 clamp */
}

.center-panel .collection-section::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  border-radius: 8px;
  padding: 1px;
  background: linear-gradient(45deg, #00d4ff, #0066cc, #00d4ff);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: exclude;
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask-composite: exclude;
  pointer-events: none;
}

.center-panel .collection-header { margin-bottom: 12px; }

.center-panel .collection-title-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
}

.center-panel .collection-title-decoration {
  height: 1px;
  background: linear-gradient(90deg, transparent, #00d4ff, transparent);
  flex: 1;
}

.center-panel .collection-title-decoration.left { margin-right: 15px; }
.center-panel .collection-title-decoration.right { margin-left: 15px; }

.center-panel .collection-title {
  color: #00d4ff;
  font-size: 16px;
  font-weight: bold;
  text-shadow: 0 0 10px #00d4ff;
  white-space: nowrap;
  letter-spacing: 1px;
}

.collection-grid {
  /* 不换行：固定单行四列，填满容器剩余空间 */
  flex: 1 1 auto;
  min-height: 0; /* 允许在弹性容器内正确压缩/展开 */
  width: 100%;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr)); /* 始终四列，不随屏幕变更 */
  grid-template-rows: 1fr; /* 单行，高度占满容器 */
  align-items: stretch;
  gap: var(--collection-gap);
}

.collection-item {
  /* 卡片自适应：填满网格单元，内部间距随尺寸调整 */
  display: flex;
  flex-direction: column; /* 垂直布局：图标在上，文字在下 */
  align-items: center;
  justify-content: center;
  gap: clamp(8px, 1.2vw, 14px);
  padding: clamp(10px, 1.5vw, 16px);
  background: rgba(0, 212, 255, 0.05);
  border: 1px solid rgba(0, 212, 255, 0.25);
  border-radius: 6px;
  transition: all 0.25s ease;
  height: 100%; /* 让卡片高度占满格子 */
}

.collection-item:hover {
  border-color: #00d4ff;
  box-shadow: 0 0 12px rgba(0, 212, 255, 0.2);
}

.stat-icon {
  /* 图标基座：用于承载不同图形组合 */
  /* 图标尺寸自适应，保留正方形比例 */
  width: clamp(48px, 11vw, 84px);
  aspect-ratio: 1 / 1;
  border-radius: 10px;
  border: 1px solid rgba(0, 212, 255, 0.5);
  box-shadow: 0 0 10px rgba(0, 212, 255, 0.3), inset 0 0 10px rgba(0, 212, 255, 0.15);
  background: radial-gradient(circle at 30% 30%, rgba(0, 212, 255, 0.25) 0%, rgba(10, 20, 40, 0.9) 70%);
  position: relative;
  overflow: hidden;
}

/* 标题科技感边框与霓虹质感 */
.title-framed {
  padding: 4px 12px;
  border: 1px solid rgba(0, 212, 255, 0.6);
  border-radius: 6px;
  box-shadow: 0 0 12px rgba(0, 212, 255, 0.4), inset 0 0 8px rgba(0, 212, 255, 0.25);
  background: linear-gradient(180deg, rgba(0, 212, 255, 0.08), rgba(0, 212, 255, 0.02));
}

.stat-icon.icon-total { background: radial-gradient(circle at 30% 30%, #00e5ff 0%, #0a1428 60%); }
.stat-icon.icon-used { background: radial-gradient(circle at 30% 30%, #00c2ff 0%, #0a1428 60%); }
.stat-icon.icon-available { background: radial-gradient(circle at 30% 30%, #00ffc6 0%, #0a1428 60%); }
.stat-icon.icon-projects { background: radial-gradient(circle at 30% 30%, #66a6ff 0%, #0a1428 60%); }
.stat-icon.icon-volumes { background: radial-gradient(circle at 30% 30%, #55ddff 0%, #0a1428 60%); }
.stat-icon.icon-involumes { background: radial-gradient(circle at 30% 30%, #5fdde5 0%, #0a1428 60%); }
.stat-icon.icon-pages { background: radial-gradient(circle at 30% 30%, #88f0ff 0%, #0a1428 60%); }
.stat-icon.icon-digital { background: radial-gradient(circle at 30% 30%, #00ffe5 0%, #0a1428 60%); }
.stat-icon.icon-utilization { background: radial-gradient(circle at 30% 30%, #44e4ff 0%, #0a1428 60%); }

.stat-content { display: flex; flex-direction: column; }
.stat-value {
  color: #00d4ff;
  /* 数值自适应：随容器尺寸增大但保持合理边界 */
  font-size: clamp(18px, 1.8vw, 28px);
  font-weight: bold;
  line-height: 1.2;
  text-shadow: 0 0 8px rgba(0, 212, 255, 0.6);
}
.stat-label {
  color: #8cc8ff;
  /* 标签自适应：避免在大容器里显得过小 */
  font-size: clamp(12px, 1.2vw, 16px);
}

/* 图标内部元素基类（最多三层） */
.stat-icon .i { position: absolute; display: block; }

/* 1) 多彩文件夹（绿、黄、蓝）用于：案卷数 */
.icon-folder-multi .i1,
.icon-folder-multi .i2,
.icon-folder-multi .i3 {
  width: 32px;
  height: 22px;
  border-radius: 3px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
}
.icon-folder-multi .i1 { /* 蓝色底层文件夹 */
  left: 8px; top: 25px;
  background: linear-gradient(180deg, #2ecbff, #0aa2d8);
}
.icon-folder-multi .i2 { /* 黄色中层文件夹 */
  left: 12px; top: 18px;
  background: linear-gradient(180deg, #ffd93d, #ffaa00);
}
.icon-folder-multi .i3 { /* 绿色前景文件夹 */
  left: 16px; top: 11px;
  background: linear-gradient(180deg, #00ffb0, #00c686);
}
.icon-folder-multi .i1::before,
.icon-folder-multi .i2::before,
.icon-folder-multi .i3::before {
  /* 文件夹顶部标签 */
  content: '';
  position: absolute;
  width: 10px; height: 6px;
  border-radius: 2px 2px 0 0;
  left: 4px; top: -4px;
  background: rgba(255, 255, 255, 0.25);
}

/* 2) 紫色圆形（堆叠文件 + 放大镜）用于：卷内件数 */
.icon-stack-search {
  background: radial-gradient(circle at 50% 50%, #b47cff 0%, #5f31b8 70%);
}
.icon-stack-search .i1, /* 底部文件 */
.icon-stack-search .i2, /* 上层文件 */
.icon-stack-search .i3  /* 放大镜 */ { }
.icon-stack-search .i1 {
  left: 12px; top: 26px; width: 22px; height: 14px; border-radius: 2px;
  background: linear-gradient(180deg, #6bd1ff, #1b80bf);
}
.icon-stack-search .i2 {
  left: 16px; top: 18px; width: 22px; height: 14px; border-radius: 2px;
  background: linear-gradient(180deg, #ffd76b, #cc8b00);
}
.icon-stack-search .i3 {
  /* 放大镜圆环 */
  left: 28px; top: 16px; width: 16px; height: 16px; border-radius: 50%;
  box-shadow: 0 0 6px rgba(255, 255, 255, 0.35);
  border: 2px solid rgba(255, 255, 255, 0.85);
}
.icon-stack-search .i3::after {
  /* 放大镜手柄 */
  content: '';
  position: absolute;
  width: 8px; height: 2px;
  background: rgba(255, 255, 255, 0.85);
  bottom: -4px; right: -2px;
  transform: rotate(35deg);
  border-radius: 1px;
}

/* 3) 蓝色文件图标用于：件数 */
.icon-doc-blue .i1 {
  left: 16px; top: 12px; width: 26px; height: 32px; border-radius: 4px;
  background: linear-gradient(180deg, #79d5ff, #1b90c7);
  box-shadow: inset 0 -4px 8px rgba(0, 0, 0, 0.25);
}
.icon-doc-blue .i1::before {
  /* 折角 */
  content: '';
  position: absolute;
  right: 0; top: 0; width: 10px; height: 10px;
  background: linear-gradient(135deg, rgba(255,255,255,0.6), rgba(0,212,255,0.6));
  clip-path: polygon(0 0, 100% 0, 100% 100%);
}

/* 4) 三个橙色六边形（1,2,3）用于：数字化率 */
.icon-hex3-orange .i1,
.icon-hex3-orange .i2,
.icon-hex3-orange .i3 {
  width: 16px; height: 16px; color: #0a0e14;
  background: linear-gradient(180deg, #ffb35c, #e07900);
  box-shadow: 0 0 6px rgba(255, 170, 0, 0.6);
  text-align: center; line-height: 16px; font-size: 10px; font-weight: bold;
}
.icon-hex3-orange .i1 { left: 16px; top: 14px; }
.icon-hex3-orange .i2 { left: 28px; top: 24px; }
.icon-hex3-orange .i3 { left: 40px; top: 34px; }
.icon-hex3-orange .i1,
.icon-hex3-orange .i2,
.icon-hex3-orange .i3 {
  /* 六边形裁剪 */
  clip-path: polygon(25% 0, 75% 0, 100% 50%, 75% 100%, 25% 100%, 0 50%);
}
.icon-hex3-orange .i1::after { content: '1'; }
.icon-hex3-orange .i2::after { content: '2'; }
.icon-hex3-orange .i3::after { content: '3'; }

/* 说明：根据用户需求，四卡片不换行，故移除小屏下的换列设置。 */

/* 滚动条样式 */
.alarm-list::-webkit-scrollbar,
.log-list::-webkit-scrollbar {
  width: 4px;
}

.alarm-list::-webkit-scrollbar-track,
.log-list::-webkit-scrollbar-track {
  background: rgba(0, 212, 255, 0.1);
  border-radius: 2px;
}

.alarm-list::-webkit-scrollbar-thumb,
.log-list::-webkit-scrollbar-thumb {
  background: rgba(0, 212, 255, 0.5);
  border-radius: 2px;
}

/* 响应式设计 */
@media (max-width: 1200px) {
  .main-content {
    grid-template-columns: 220px 1fr 280px;
  }
}

@media (max-width: 768px) {
  .main-content {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto auto;
    height: auto;
  }
}
</style>